Imports System
Imports System.Configuration
Imports System.IO
Imports System.Security.Principal
Imports System.Text

Public Class log

    Private Shared _instance As log
    Private Shared _performantie As log
    Private Shared _session As String = ""
    Private _filePath As String

    ''' <summary>
    ''' Gewone log
    ''' </summary>
    Public Shared ReadOnly Property Instance() As log
        Get
            If (_instance Is Nothing) Then
                If (AppDomain.CurrentDomain.BaseDirectory.Contains("TestResults")) Then
                    ' voor unittests omdat dan het StartupPath ergens in Program Files zit, en daar heb je geen rechten
                    _instance = New log(AppDomain.CurrentDomain.BaseDirectory & "\log.txt")
                Else
                    _instance = New log(String.Format("{0}\App_Data\logs\{1} log.txt", Application.StartupPath, Session))
                End If
            End If
            Return _instance
        End Get
    End Property

    ''' <summary>
    ''' Performantielog
    ''' </summary>
    Public Shared ReadOnly Property Performantie() As log
        Get
            If (_performantie Is Nothing) Then
                If (AppDomain.CurrentDomain.BaseDirectory.Contains("TestResults")) Then
                    ' voor unittests omdat dan het StartupPath ergens in Program Files zit, en daar heb je geen rechten
                    _performantie = New log(AppDomain.CurrentDomain.BaseDirectory)
                Else
                    _performantie = New log(String.Format("{0}\App_Data\logs\performantie.txt", Application.StartupPath))
                End If
            End If
            Return _performantie
        End Get
    End Property

    ' per sessie (vb. winkelbeurt) maken we een aparte logfile. 
    ' Hier houden we daarvoor een unieke code bij
    ' De code wordt gebruikt in de naam van de logfile
    Private Shared ReadOnly Property Session() As String
        Get
            If (_session = "") Then
                _session = DateTime.Now.ToString("yyMMddHHmmss")
            End If
            Return _session
        End Get
    End Property

#Region "Constructor en initialisatie"

    ' <summary>
    ' debug and error logger
    ' </summary>
    Private Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub

#End Region

#Region "Publieke methodes"

    Public Shared Sub WriteInfo(ByVal msg As String)
        Instance.WriteLog(msg)
    End Sub

    Public Shared Sub WriteInfo(ByVal format As String, ByVal ParamArray params() As Object)
        Dim msg As String = String.Format(format, params)
        Instance.WriteLog(msg)
    End Sub

    Public Shared Sub Debug(ByVal msg As String)
        If (IsDebugEnabled) Then Instance.WriteLog(msg)
    End Sub

    Public Shared Sub Debug(ByVal format As String, ByVal ParamArray params() As Object)
        Dim msg As String = String.Format(format, params)
        Debug(msg)
    End Sub

    Public Shared Sub WriteError(ByVal msg As String)
        If (IsErrorEnabled) Then Instance.WriteLog(msg)
    End Sub

    Public Shared Sub WriteError(ByVal format As String, ByVal ParamArray params() As Object)
        Dim msg As String = String.Format(format, params)
        WriteError(msg)
    End Sub

    Public Shared Sub WriteError(ByVal naamMethode As String, ByVal e As Exception)
        If (e Is Nothing) Then
            WriteError(naamMethode)
        Else
            WriteError(naamMethode, e.ToString())
        End If
    End Sub

    Public Shared Sub WriteError(ByVal naamMethode As String, ByVal msg As String)
        WriteError(naamMethode & Environment.NewLine & msg)
    End Sub

    Public Shared Sub LogLaatsteTelling(ByVal infoSoort As String, ByVal telling As TellingDataSet, ByVal totaal As Decimal)
        Try
            Dim logPath As String = String.Format("{0}/App_Data/logs/{1} telling.txt", Application.StartupPath, DateTime.Now.ToString("yyMMddHHmmss"))
            Using sw As New StreamWriter(logPath)
                sw.WriteLine("Telling van {0:dd/MM/yyyy hh:mm}, {1}", DateTime.Now(), infoSoort)
                sw.WriteLine("Gebruiker: {0} - {1} ", WindowsIdentity.GetCurrent().Name, Security.HuidigeWinkelierNaam)
                For Each rij As TellingDataSet.LaatsteTellingRow In telling.LaatsteTelling.Rows
                    sw.WriteLine("{0} items van {1:c} Euro", rij.Aantal, rij.Waarde)
                Next
                sw.WriteLine("Totaal in kas: {0:c}", totaal)
                sw.Flush()
                sw.Close()
            End Using
        Catch ex As Exception
            ' niets doen als er met het loggen zelf iets misgaat
        End Try
    End Sub

    Public Shared Sub WritePerformantie(ByVal msg As String)
        Performantie.WriteLog(msg)
    End Sub

#End Region

#Region "Private methods"

    Private Sub WriteLog(ByVal msg As String)
        Try
            Dim sbMsg As New StringBuilder()
            sbMsg.Append("Gebruiker: ")
            sbMsg.Append(WindowsIdentity.GetCurrent().Name)
            sbMsg.Append(" - ")
            sbMsg.Append(Security.HuidigeWinkelierNaam)
            sbMsg.Append(Environment.NewLine)
            sbMsg.Append(msg)
            Dim logFile As New FileInfo(_filePath)
            If (logFile.Exists AndAlso logFile.Length >= 100000) Then
                File.Delete(_filePath)
            End If
            If (Not logFile.Directory.Exists()) Then logFile.Directory.Create()
            Using fs As New FileStream(_filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite) ' om te kunnen toevoegen aan het bestand
                Using sw As New StreamWriter(fs)
                    sw.BaseStream.Seek(0, SeekOrigin.End) ' toevoegen aan het einde
                    If (Utility.IsOefenVersie()) Then
                        sw.Write("Oefenversie ")
                    End If
                    sw.WriteLine("* {0} {1} ", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString())
                    sw.WriteLine(sbMsg.ToString())
                    sw.WriteLine("------------------------------------")
                    sw.Flush()
                    sw.Close()
                End Using
            End Using
        Catch ex As Exception
            ' niets doen als er met het loggen zelf iets misgaat
        End Try
    End Sub

    Private Shared Function GetLevel() As String
        Dim level As String = My.Settings.loglevel
        If (level.Length >= 1) Then Return level
        Return "OFF"
    End Function

    Private Shared ReadOnly Property IsErrorEnabled() As Boolean
        Get
            Dim level As String = GetLevel()
            Return (level = "ALL" Or level = "DEBUG" Or level = "INFO" Or level = "WARN" Or level = "ERROR")
        End Get
    End Property

    Private Shared ReadOnly Property IsDebugEnabled() As Boolean
        Get
            Dim level As String = GetLevel()
            Return (level = "ALL" Or level = "DEBUG")
        End Get
    End Property

#End Region

End Class
